package com.apes.fn.server.productRequireManage.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.scm.masterdata.enumeration.model.BusinessParam;
import com.apes.scm.masterdata.enumeration.repository.BusinessParamRepository;
import com.apes.fn.server.productRequire.ProductRequire;
import com.apes.fn.server.productRequire.ProductRequireItem;
import com.apes.fn.server.productRequire.ProductRequireRepository;
import com.apes.fn.server.productRequire.ProductRequireService;
import com.apes.fn.server.productRequireManage.model.ParameterTransfer;
import com.apes.fn.server.productRequireManage.model.ReplenishmentBusinessImpAbstract;
import com.apes.framework.api.SpringManager;
import com.apes.framework.plugin.esb.processor.idempotent.AntiHeavy;
import com.apes.framework.plugin.esb.processor.idempotent.AntiHeavyRepository;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.OutboxSubscriberService;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.plugin.soe.store.database.repository.BusinessAttributeValueRepository;
import com.apes.framework.plugin.soe.store.database.repository.SceneRepository;
import com.apes.framework.util.MapUtil;
import com.apes.pi.service.PiManager;
import com.apes.scm.account.tax.repository.TaxRepository;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.enumeration.repository.EnumerationRepository;
import com.apes.scm.masterdata.frame.model.Store;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.frame.repository.StoreRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import com.apes.scm.masterdata.stock.model.PhyDepot;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrder;
import com.apes.scm.pur.purchaseOrder.model.PurchaseOrderItem;
import com.apes.scm.pur.purchaseOrder.service.PurchaseService;
import com.apes.scm.rbac.model.User;
import com.apes.scm.rbac.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service("baturuPurOrderService")
public class BaturuPurOrderService extends ReplenishmentBusinessImpAbstract {

    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private PiManager piManager;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private TaxRepository taxRepository;
    @Autowired
    private OutboxSubscriberService outboxSubscriberService;
    @Autowired
    private ProductRequireRepository productRequireRepository;
    @Autowired
    private ProductUomRepository productUomRepository;
    @Autowired
    private UserRepository userRepository;
    @Autowired
    private ProductRequireService productRequireService;
    @Autowired
    private PurchaseService purchaseService;

    // 创建采购订单、巴图鲁采购订单
    public void baturuCreatePurchaseOrder(ProductRequire require) {
        ProductRequireItem requrieItem = require.getProductRequireItems().stream().filter(requireItem -> {
            return StringUtils.hasText(requireItem.getCommodityInquiryOrderId()) && requireItem.getCommodityInquiryOrderId().startsWith("BI") && requireItem.getQtyRequire() - requireItem.getQtyAssigned() > 0;
        }).findFirst().orElse(null);
        if (ObjectUtils.isEmpty(requrieItem)) return;
        PurchaseOrder purchaseOrder = this.appendPurchaseOrder(require);
        purchaseOrder.setSupplierType("巴图鲁采购订单"); // 有用到

        JSONArray baturuOrderData = new JSONArray();
        List<PurchaseOrderItem> purchaseItems = new ArrayList<>();
        Map carrierInfoCache = new HashMap<>();
        require.getProductRequireItems().stream().filter(requireItem -> StringUtils.hasText(requireItem.getCommodityInquiryOrderId()) && requireItem.getCommodityInquiryOrderId().startsWith("BI")).forEach(requireItem -> { // 根据站点分组，巴图鲁只有一个站点，不用考虑
            JSONObject spxjdzxbObj = piManager.synErp("scmGysxjdService.queryBaturuoffer", MapUtil.mapper("XJDH", requireItem.getCommodityInquiryOrderId(), "SPID", requireItem.getProduct().getId()));
            JSONObject xjzxbData = spxjdzxbObj.getJSONObject("obj"); // 考虑报错情况
            if (xjzxbData == null || xjzxbData.isEmpty() || !spxjdzxbObj.getBooleanValue("success")) return;
            double requireQty = requireItem.getQtyRequire();

            ParameterTransfer parameterTransfer = new ParameterTransfer(requireItem.getProduct().getId(), requireItem.getCommodityInquiryOrderId(), require.getSource(),
                    requireQty, purchaseOrder.getContract().getSettlementType(), xjzxbData);
            parameterTransfer.setCarrier(carrierInfoCache);

            purchaseItems.add(this.appendPurchaseOrderItem(purchaseOrder, requireItem, parameterTransfer));

            // 拼接巴图鲁数据
            baturuOrderData.addAll(this.appendBaturuOrderItem(parameterTransfer));
            carrierInfoCache.putAll(parameterTransfer.getCarrier());
        });
        if (baturuOrderData.isEmpty()) {
            return;
        }

        JSONObject baturuCreateOrderData = this.appendBaturuOrder(require);
        baturuCreateOrderData.put("orderDetails", baturuOrderData);
        purchaseOrder.setPurchaseItems(purchaseItems);
        PurchaseOrder newOrder = invoke("purchase.order.create", MapUtil.mapped(purchaseOrder));
        newOrder.setState("confirmed");
        newOrder = invoke("purchase.order.approve", MapUtil.mapped(newOrder));
        outboxSubscriberService.commonSendRequest("local:ProductRequireService.sendBturuOrder", "sendBturuOrder: " + require.getId(),
                new JSONObject(MapUtil.mapper("data", baturuCreateOrderData, "requireId", require.getId())));
        System.out.println(newOrder.getId());
    }

    @Override
    public Map sendOrder(JSONObject getJO) {
        Map carrierInfoCache = new HashMap<>();
        getJO.getJSONArray("purchaseRequireItems").stream()
                .collect(Collectors.groupingBy(getJORequireItem -> {return ((JSONObject) getJORequireItem).getString("productRequireId");}))
                .forEach((k, v) -> {
                    ProductRequire require = productRequireRepository.findOne(k);
                    PurchaseOrder purchaseOrder = this.appendPurchaseOrder(require);
                    purchaseOrder.setSupplierType("巴图鲁采购订单");
                    JSONArray baturuItemArray = new JSONArray();
                    v.forEach(requireItemV -> {
                        JSONObject requireItemObj = (JSONObject) requireItemV;
                        String reqItemId = requireItemObj.getString("id");
                        double distributionQty = requireItemObj.getDoubleValue("distributionQty");
                        // 组装采购、巴图鲁信息
                        require.getProductRequireItems().stream()
                                .filter(requireItemB -> {return requireItemB.getId().equals(reqItemId) && requireItemB.getQtyRequire() - requireItemB.getQtyEnd() - requireItemB.getQtyAssigned() - requireItemB.getOrderQty() > 0;})
                                .forEach(requireItemB2 -> {
                                    Map orderItem = this.appendOrderItem(require, requireItemB2, carrierInfoCache, purchaseOrder, distributionQty);
                                    if (orderItem.isEmpty()) return;
                                    purchaseOrder.getPurchaseItems().add((PurchaseOrderItem) orderItem.get("purchaseOrderItem")); // 改变条数了????????????????
                                    baturuItemArray.addAll((JSONArray)orderItem.get("baturuOrderItem"));
                                });


                    });
                    // 通知创建订单
                    if (baturuItemArray.isEmpty()) return;
                    this.sendPurchaseOrderRequest(purchaseOrder);
                    this.noticCreateOrder(baturuItemArray, require);
        });
        return new HashMap();
    }

    // 拼接巴图鲁、采购订单明细
    private Map appendOrderItem(ProductRequire require, ProductRequireItem requireItem, Map carrierInfoCache, PurchaseOrder purchaseOrder, double purQty) {
        Map item = new HashMap();

        JSONObject spxjdzxbObj = piManager.synErp("scmGysxjdService.queryBaturuoffer", MapUtil.mapper("XJDH", requireItem.getCommodityInquiryOrderId(), "SPID", requireItem.getProduct().getId()));
        JSONObject xjzxbData = spxjdzxbObj.getJSONObject("obj");
        if (xjzxbData == null || xjzxbData.isEmpty() || !spxjdzxbObj.getBooleanValue("success")) return new HashMap();

        ParameterTransfer parameterTransfer = new ParameterTransfer(requireItem.getProduct().getId(), requireItem.getCommodityInquiryOrderId(), require.getSource(),
                purQty, purchaseOrder.getContract().getSettlementType(), xjzxbData);
        parameterTransfer.setCarrier(carrierInfoCache);

        item.put("purchaseOrderItem", this.appendPurchaseOrderItem(purchaseOrder, requireItem, parameterTransfer));

        // 拼接巴图鲁数据
        item.put("baturuOrderItem", this.appendBaturuOrderItem(parameterTransfer));
        carrierInfoCache.putAll(parameterTransfer.getCarrier());

        return item;
    }

    // 发送通知到事务发件箱 - 巴图鲁采购订单
    public void noticCreateOrder(JSONArray baturuOrderItemData, ProductRequire require) {
        JSONObject baturuCreateOrderData = this.appendBaturuOrder(require);
        baturuCreateOrderData.put("orderDetails", baturuOrderItemData);
        outboxSubscriberService.commonSendRequest("local:ProductRequireService.sendBturuOrder", "sendBturuOrder: " + require,
                new JSONObject(MapUtil.mapper("data", baturuCreateOrderData, "requireId", require.getId())));
    }

    // 发送创建采购订单请求
    private String sendPurchaseOrderRequest(PurchaseOrder purchaseOrder) {
        PurchaseOrder newOrder = invoke("purchase.order.create", MapUtil.mapped(purchaseOrder));
        newOrder.setState("confirmed");
        newOrder.setApproveUid(newOrder.getCreateUid());
        invoke("purchase.order.approve", MapUtil.mapped(newOrder));
        return newOrder.getId();
    }

    @OutboxSubscriber(id = "local:ProductRequireService.sendBturuOrder", name = "推送订单到巴图鲁")
    public void sendBturuOrder(OutboxPayloadWrapper outboxPayloadWrapper) {
        JSONObject payload = JSONObject.parseObject(outboxPayloadWrapper.getPayload());
        String requireId = payload.getString("requireId");

        // 推送巴图鲁
        String existsBaturuOrderId = this.existsAntiHeavy(requireId);
        JSONObject baturuOrderInfo = new JSONObject();
        JSONObject body = new JSONObject();
        if (StringUtils.isEmpty(existsBaturuOrderId)) {
            baturuOrderInfo = JSONObject.parseObject(invoke("stock.productRequireService.createOrder", payload.getJSONObject("data")));
            body = baturuOrderInfo.getJSONObject("body");
            if (body.getBooleanValue("success")) this.tempSaveAntiHeavy("sendBturuOrder." + requireId + "." + body.getString("model"));
        }

        if (!body.isEmpty() && !body.getBooleanValue("success")) { // 推送异常
            updateInterfacepushFail(body.getString("msg"), requireId);
            purchaseService.saveBaturuNotice("推送订单到巴图鲁失败", new JSONObject(MapUtil.mapper("requireId", requireId, "errorContent", body.getString("msg"))));

            // 处理已经生成的采购订单
            purchaseService.baturuFailCancel(requireId);
        } else {
            String model = StringUtils.isEmpty(existsBaturuOrderId)?body.getString("model"):existsBaturuOrderId;
            purchaseService.updateSupplierRef(model, requireId);
        }


    }

    // 修改巴图鲁推送失败备注
    public void updateInterfacepushFail(String interfacePushFail, String requireId) {
        ProductRequire require = productRequireRepository.findOne(requireId);
        require.setInterfacePushFail(interfacePushFail + "");
        productRequireService.save(require);
    }

    // 是否存在巴图鲁订单
    private String existsAntiHeavy(String requireId) {
        AntiHeavy antiHeavy = SpringManager.getBean(AntiHeavyRepository.class).fuzzySearch("sendBturuOrder." + requireId);
        if (antiHeavy != null) {
            return antiHeavy.getId().split("\\.")[2];
        } else {
            return "";
        }
    }

    // 巴图鲁防重处理
    private void tempSaveAntiHeavy(String id) {
        try {
            AntiHeavy antiHeavy = new AntiHeavy();
            antiHeavy.setId(id);
            SpringManager.getBean(AntiHeavyRepository.class).save(antiHeavy);
        } catch (Exception e) {
        }
    }


    // 拼接采购订单
    private PurchaseOrder appendPurchaseOrder(ProductRequire require) {
        PurchaseOrder purchaseOrder = new PurchaseOrder();
        BusinessParam businessParam = getBean(BusinessParamRepository.class).findAllByQueryKey("baturuSupplier").get(0);
        PartyRole supplier = partyRoleRepository.findValidSupplier(businessParam.getValue(), businessParam.getValue());
        if (ObjectUtils.isEmpty(supplier)) supplier = partyRoleRepository.findValidSupplier("000286", "000286");

        List<Contract> contracts = SpringManager.getBean(ContractRepository.class).findValidPlatform(supplier);
        Contract contract = contracts.get(0);
        purchaseOrder.setScene(SpringManager.getBean(SceneRepository.class).findOne("PO001"));
        purchaseOrder.setCreator(require.getApproveId().getId());
        purchaseOrder.setCreateUid(require.getApproveId());
        purchaseOrder.setState("approve");
        purchaseOrder.setMoveType(SpringManager.getBean(EnumerationRepository.class).findOne("one"));
        purchaseOrder.setClerk(require.getApproveId());
        purchaseOrder.setContract(contract);
        purchaseOrder.setCooperation(contract.getCooperation());
        purchaseOrder.setLocation(require.getLocation());
        purchaseOrder.setSupplier(supplier);
        purchaseOrder.setApproveUid(require.getApproveId());
        purchaseOrder.setDateApprove(require.getApproveDate());
        purchaseOrder.setOrigin(require.getId());
        purchaseOrder.setOriginBusinessType(require.getInnerBusinessType());
        purchaseOrder.setOriginTypeName("要货单");
        purchaseOrder.setCarryType(SpringManager.getBean(BusinessAttributeValueRepository.class).findOne(contract.getCarryType().getId()));
        purchaseOrder.setProductRequire(require.getId());
        purchaseOrder.setSource(require.getId());
        purchaseOrder.setSourceType(require.getInnerBusinessType());
        purchaseOrder.setSourceTypeName("要货单");
        if (require.getProductRequireItems().get(0).getSite() != null) {
            purchaseOrder.setSiteId(require.getProductRequireItems().get(0).getSite().getId());
            purchaseOrder.setSiteName(require.getProductRequireItems().get(0).getSite().getName());
        }
        if (!Objects.isNull(require.getCustomerExpand())) {
            purchaseOrder.setCustomerExpandId(require.getCustomerExpand().getId());
            purchaseOrder.setCarLicense(require.getCustomerExpand().getCarLicense());
        }
//        String systemEnvironment = SpringManager.getBean(BusinessParamRepository.class).findOne("20").getValue();
        purchaseOrder.setPurchasingGroup(businessParam.getValue3());
        if (contract.getCompany().getId().equals("1007")) {
            purchaseOrder.setDept(deptRepository.findByDeptTypeIdAndCompanyId("000006", require.getLocation().getCompany().getId()));
            purchaseOrder.setCompany(require.getLocation().getCompany());
        } else {
            purchaseOrder.setDept(contract.getDept());
            purchaseOrder.setCompany(contract.getCompany());
        }

        return purchaseOrder;
    }

    // 采购订单明细
    private PurchaseOrderItem appendPurchaseOrderItem(PurchaseOrder purchaseOrder, ProductRequireItem requireItem, ParameterTransfer parameterTransfer) {
        PurchaseOrderItem purchaseItem = new PurchaseOrderItem();
        purchaseItem.setSourceItemId(requireItem.getId());
        purchaseItem.setProduct(requireItem.getProduct());
        purchaseItem.setTax(taxRepository.findOne(Long.valueOf("5")));
        purchaseItem.setPriceUnit(parameterTransfer.getXjzxbData().getDoubleValue("CGDJ"));
        purchaseItem.setSolicitationQty(0);
        purchaseItem.setSourceState(requireItem.getSourceState());
        purchaseItem.setExpectedArrivalTime(requireItem.getExpectedArrivalTime());
        purchaseItem.setSettlementType(parameterTransfer.getSettlementType());
        purchaseItem.setExternalCode(parameterTransfer.getXjzxbData().getString("WYZ"));
        purchaseItem.setPurchaseOrder(purchaseOrder);
        this.conversionUomQty(purchaseItem, requireItem.getUom(), parameterTransfer.getRequireQty());
        purchaseItem.computeAmt();
        return purchaseItem;
    }

    // 巴图鲁采购订单明细
    private JSONArray appendBaturuOrderItem(ParameterTransfer pt) {
        // 查询承运信息、是否制定承运
//        List<Map> findCarrierInfos =
//                SpringManager.getBean(ServicePlanItemRepository.class).findCarrier(pt.getCommodiInquiry(), pt.getProductId(), pt.getRequireSource());
//        if (findCarrierInfos.isEmpty() || StringUtils.isEmpty(findCarrierInfos.get(0).get("CARRIER_ID"))) return new JSONArray();
        JSONArray orderDetails = new JSONArray();
        JSONObject orderDetail = new JSONObject();
        orderDetail.put("priceNo", pt.getXjzxbData().getString("WYZ"));
        orderDetail.put("num", pt.getRequireQty());
        orderDetail.put("invoiceType", -1);


//        Map carrierInfo = pt.getCarrier();
//        long externalGysid = pt.getXjzxbData().getLongValue("EXTERNAL_GYSID");
//        boolean carrierFlag = StringUtils.isEmpty(findCarrierInfos.get(0).get("CARRIER_ID"));
        orderDetail.put("specificCarrier", /*!carrierFlag*/true);
        orderDetail.put("carrierId", -10L);
        orderDetail.put("carrierName", "其他物流");
       /* if (!carrierInfo.containsKey(externalGysid) && !carrierFlag) {
            carrierInfo.put(externalGysid,
                    MapUtil.mapper("CARRIER_ID", findCarrierInfos.get(0).get("CARRIER_ID"), "CARRIER_NAME", findCarrierInfos.get(0).get("CARRIER_NAME")));
        }
        if (carrierInfo.containsKey(externalGysid)) {
            Map cacheCarrierInfo = ((Map) carrierInfo.get(Long.valueOf(externalGysid)));
            orderDetail.put("carrierId", cacheCarrierInfo.get("CARRIER_ID"));
            orderDetail.put("carrierName", cacheCarrierInfo.get("CARRIER_NAME"));
        }*/
        orderDetails.add(orderDetail);
        return orderDetails;
    }

    // 单位换算
    private void conversionUomQty(ProductRequireItem requireItem, PurchaseOrderItem purchaseItem) {
        double requireQty = requireItem.getQtyRequire();
        if (requireItem.getUom().isPurchaseFirst()) {
            purchaseItem.setUom(requireItem.getUom());
        } else {
            ProductUom purchaseUom = productUomRepository.findBypurchaseUom(requireItem.getProduct().getId());
            purchaseItem.setUom(purchaseUom);
            requireQty = requireItem.getUom().computeQty(requireQty, purchaseUom, true);
        }
        purchaseItem.setEffectiveQty(requireQty);
        purchaseItem.setProductUomQty(requireQty);
        purchaseItem.setDemandQty(requireQty);
    }

    // 单位换算
    private void conversionUomQty(PurchaseOrderItem purchaseItem, ProductUom currentUom, double purQty) {
        if (currentUom.isPurchaseFirst()) {
            purchaseItem.setUom(currentUom);
        } else {
            ProductUom purchaseUom = productUomRepository.findBypurchaseUom(purchaseItem.getProduct().getId());
            purchaseItem.setUom(purchaseUom);
        }
        purchaseItem.setEffectiveQty(purQty);
        purchaseItem.setProductUomQty(purQty);
        purchaseItem.setDemandQty(purQty);
    }

    // 拼接巴图鲁采购订单
    private JSONObject appendBaturuOrder(ProductRequire require) {
        Map obtainCreator = productRequireRepository.obtainCreator(require.getId());
        List<User> user = userRepository.findByPartyRoleId(obtainCreator.get("CREATOR_ID").toString());
        JSONObject mainData = new JSONObject();

        // 需验证和服务方案、巴图鲁账号数据，老系统有啥区别 ???
        Store store = getBean(StoreRepository.class).findByDept(require.getLocation().getDepot().getDept());
        mainData.put("storeId", store.getCode());
        mainData.put("receiverName", user.get(0).getName());
        mainData.put("receiverPhone", user.get(0).getMobileNumber());
        mainData.put("bothPay", true);
        mainData.put("payType", 2);


        PhyDepot phyDepot = require.getLocation().getPhyDepot();
        JSONObject receiverAddress = new JSONObject();
        receiverAddress.put("location", store.getLongitude() +"," + store.getLatitude());
        receiverAddress.put("address", store.getAddress());
        mainData.put("receiverAddress", receiverAddress);
        return mainData;
    }
}
